home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 2 / AACD 2.iso / AACD / Online / Socks5 / src / server / validate.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-06-22  |  36.5 KB  |  936 lines

  1. /* Copyright (c) 1995-1999 NEC USA, Inc.  All rights reserved.               */
  2. /*                                                                           */
  3. /* The redistribution, use and modification in source or binary forms of     */
  4. /* this software is subject to the conditions set forth in the copyright     */
  5. /* document ("Copyright") included with this distribution.                   */
  6.  
  7. /*
  8.  * $Id: validate.c,v 1.74.2.1.2.9 1999/03/05 21:52:50 steve Exp $
  9.  */
  10.  
  11. /* This file contains all of the stuff associated with parsing the config    */
  12. /* file, except for some utility routines which appear in valutil.c.  The    */
  13. /* routines for checking the parsed config file appear in check.c.           */
  14. #include "socks5p.h"
  15. #include "threads.h"
  16. #include "daemon.h"
  17. #include "confutil.h"
  18. #include "validate.h"
  19. #include "protocol.h"
  20. #include "msgids.h"
  21. #include "info.h"
  22. #include "log.h"
  23.  
  24. #define INVALID_TYPE (char)-1   /* some kind of config error...               */
  25.  
  26. IFTHREADED(static MUTEX_T confid_mutex = MUTEX_INITIALIZER;)
  27. static struct intfc *intfcs = NULL;
  28. static int ifcnt = 0;
  29.  
  30. struct sroute {
  31.     char type;
  32.     int calloced;
  33.     struct in_addr ifaddr;
  34.     struct intfc *ifp;
  35. };
  36.  
  37. struct authtuple {
  38.     int realline;
  39.     struct host source;
  40.     struct port sport;
  41.     list *authlist;
  42.     u_char banned;
  43. };
  44. typedef struct authtuple AuthTuple;
  45. static AuthTuple *authList = NULL; /* An array of auth list entries          */
  46. static int nalines = 0, na = 0;    /* how many auth lines, and current index */
  47.  
  48. /* A configuration tuple, used in the access control portion of the config   */
  49. /* file...It tells us the permission as well as matching information...      */
  50. struct conftuple {
  51.     int realline;
  52.     char permit;
  53.     list *command;
  54.     list *userlist;
  55.     list *authlist;
  56.  
  57.     struct host source, dest;
  58.     struct port sport, dport;
  59. };
  60. typedef struct conftuple ConfTuple;
  61. static ConfTuple *accessList  = NULL; /* An array of access list entries     */
  62. static int nplines = 0, np = 0;        /* how many access lines, & index      */
  63.  
  64. /* A routing tuple...used in the routing portion of the config file to tell  */
  65. /* the server how it should be connecting (and being connected) to hosts...  */
  66. struct routetuple {
  67.     int realline;
  68.     struct host source;
  69.     struct port sport;
  70.     struct sroute nexthop;
  71. };
  72. typedef struct routetuple RouteTuple;
  73. static RouteTuple *routeList = NULL; /* An array of route list entries       */
  74. static int nrlines = 0, nr = 0;       /* how many route lines, & index        */
  75.  
  76. /* A proxy tuple...used in the proxy portion of the config file to tell the  */
  77. /* server how it should get to a destination (what the next step is...)      */
  78. struct proxytuple {
  79.     int realline;
  80.     struct host source;
  81.     struct port sport;
  82.     
  83.     u_char  nextver;
  84.     S5NetAddr nextaddr[S5_SERVER_NUM];
  85.     int nnextaddr;
  86. };
  87. typedef struct proxytuple ProxyTuple;
  88. static ProxyTuple *proxyList = NULL; /* An array of socks list entries       */
  89. static int nslines = 0, ns = 0;       /* how many proxy lines & index         */
  90.  
  91. /* A filter tuple, used in the filter portion of the config file...It tells  */
  92. /* us the what filter to use for a given connection...                       */
  93. struct filtertuple {
  94.     int realline;
  95.     char name[S5_NAME_SIZE];
  96.  
  97.     list *command;
  98.     list *userlist;
  99.     list *authlist;
  100.  
  101.     struct host source, dest;
  102.     struct port sport, dport;
  103. };
  104. typedef struct filtertuple FilterTuple;
  105. static FilterTuple *filterList = NULL; /* An array of socks list entries     */
  106. static int nflines = 0, nf = 0;         /* how many filter lines & index      */
  107.  
  108. static char **varList = NULL;    /* A list of variables allocated            */
  109. static int nvlines = 0, nv = 0;   /* how many variable lines and cur index    */
  110.  
  111. extern void AuthsHandler  P((void **, int, int, char *)); /* Auth line       */
  112. extern void PermsHandler  P((void **, int, int, char *)); /* permission line */
  113. extern void HowtoHandler  P((void **, int, int, char *)); /* proxy line...   */
  114. extern void RouteHandler  P((void **, int, int, char *)); /* route line...   */
  115. extern void EvarsHandler  P((void **, int, int, char *)); /* evar line..     */
  116. extern void FilterHandler P((void **, int, int, char *)); /* filter line...  */
  117.  
  118. confid confids[] = {
  119.     { "permit",  "p",   PermsHandler, (void **)&accessList, &nplines, &np, sizeof(ConfTuple)    },
  120. #define PERMIT_IND  0 /* An indentifier that this line is "permit"            */
  121.     { "deny",    "d",   PermsHandler, (void **)&accessList, &nplines, &np, 0                    },
  122. #define DENY_IND    1 /* An indentifier that this line is "deny"              */
  123.     { "route",   "r",   RouteHandler, (void **)&routeList,  &nrlines, &nr, sizeof(RouteTuple)   },
  124. #define ROUTE_IND   2 /* An indentifier that this line is "route"             */
  125.     { "interface",   "i",   RouteHandler, (void **)&routeList,  &nrlines, &nr, 0    },
  126. #define INTFC_IND   3 /* An indentifier that this line is "interface"         */
  127.     { "socks4",  "4",   HowtoHandler, (void **)&proxyList,  &nslines, &ns, 0                    },
  128. #define SOCKS4_IND  4 /* An indentifier that this line is "socks"             */
  129.     { "socks5",  "5",   HowtoHandler, (void **)&proxyList,  &nslines, &ns, sizeof(ProxyTuple)   },
  130. #define SOCKS5_IND  5 /* An indentifier that this line is "socks5"            */
  131.     { "noproxy", "n",   HowtoHandler, (void **)&proxyList,  &nslines, &ns, 0                    },
  132. #define DIRECT_IND  6 /* An indentifier that this line is "direct"            */
  133.     { "auth",    "a",   AuthsHandler, (void **)&authList,   &nalines, &na, sizeof(AuthTuple)    },
  134. #define AUTH_IND    7 /* An indentifier that this line is "auth"              */
  135.     { "ban",     "b",   AuthsHandler, (void **)&authList,   &nalines, &na, 0                    },
  136. #define BAN_IND     8 /* An indentifier that this line is "ban"               */
  137.     { "set",     "s",   EvarsHandler, (void **)&varList,     &nvlines, &nv, sizeof(char *)      },
  138. #define SET_IND     9 /* An indentifier that this line is "set"               */
  139.     { "filter",  "f",   FilterHandler,(void **)&filterList,  &nflines, &nf, sizeof(FilterTuple) },
  140. #define FILTER_IND  10 /* An indentifier that this line is "filter"            */
  141. };
  142. #define NCONFIDS (sizeof(confids)/sizeof(struct confid))
  143.  
  144. /* Look at the buffer that ptr points to, and read either a net address of a */
  145. /* valid interface or the name (e.g. ef0, ef1, le0) of a valid int address.  */
  146. /*                                                                           */
  147. /* Arguments: ptr  -- a ptr to the buffer we are working with...(in/out)     */
  148. /*            val  -- a ptr to the address we are looking up...(out)         */
  149. static int lsGetHostOrIntfc(char **ptr, struct sroute *val) {
  150.     struct in_addr guess;
  151.     char *tmp, tc;
  152.     int i, j;
  153.  
  154.     /* XXX ipv6 support here may get messy...                                */
  155.     memset((char *)val, 0, sizeof(struct sroute));
  156.     val->type = INVALID_TYPE;
  157.  
  158.     SKIPSPACE(*ptr);
  159.     tmp = *ptr;
  160.  
  161.     SKIPNONSPACE(tmp);
  162.     tc = *tmp; *tmp = '\0';
  163.  
  164.     if ((guess.s_addr = inet_addr(*ptr)) == INVALIDADDR) {
  165.    val->type = NAME;
  166.    val->ifp = NULL;
  167.  
  168.    for (i = 0; i < ifcnt; i++) {
  169.        if (strcmp(*ptr, intfcs[i].name)) continue;
  170.  
  171.        val->ifp  = &intfcs[i];
  172.        break;
  173.    }
  174.  
  175.    if (val->ifp == NULL && (val->ifp = (struct intfc *)calloc(1, sizeof(struct intfc)))) {
  176.        strncpy(val->ifp->name, *ptr, 16);
  177.        val->ifp->name[15] = '\0';
  178.        val->calloced = 1;
  179.    }
  180.     } else {
  181.    val->type = IN_ADDR;
  182.    val->ifaddr.s_addr = guess.s_addr;
  183.    val->ifp = NULL;
  184.  
  185.    for (i = 0; i < ifcnt; i++) {
  186.        for (j = 0; j < intfcs[i].addrcnt; j++) {
  187.            if (intfcs[i].addrlist[j].ip.s_addr == guess.s_addr) break;
  188.        }
  189.  
  190.        if (j < intfcs[i].addrcnt) {
  191.       val->ifp = &intfcs[i];
  192.          break;
  193.        }
  194.    }
  195.     }
  196.  
  197.     *(*ptr = tmp) = tc;
  198.     return (val->type == INVALID_TYPE)?-1:0;
  199. }
  200.  
  201. /* myunsetenv goes through and finds a variable=value pair which is the same */
  202. /* as (char *)n.  Once it finds it, it switches it with the last variable in */
  203. /* the environment, and returns...                                           */
  204. /*                                                                           */
  205. /* Arguments: n -- the name=value pair we are looking for (just name)        */
  206. /*                                                                           */
  207. /* Globals affected: environ -- no longer contians n.                        */
  208. static void myunsetenv(void *n) {
  209. #ifdef HAVE_UNSETENV
  210.     unsetenv((char *)n);
  211.     free(n);
  212. #else
  213.     char *name = (char *)n, **tmp, **end;
  214.     extern char **environ;
  215.  
  216.     for (tmp = environ; *tmp; tmp++) 
  217.    if (!strncmp(name, *tmp, strlen(name))) break; /* find a match...    */
  218.  
  219.     if (!*tmp) return;                /* no match, so give up...             */
  220.     for (end = tmp; *(end+1); end++); /* find last set variable...           */
  221.  
  222.     *tmp = *end;                      /* switch with the last set var...     */
  223.     *end = NULL;                      /* zero out the last set var...        */
  224.     free(name);
  225. #endif
  226. }
  227.  
  228. #ifndef HAVE_SETENV
  229. static int myputenv(char *name) {
  230. #ifdef HAVE_PUTENV
  231.     return putenv(name);
  232. #else
  233.     char **tmp, *end = strchr(name, '='), c;
  234.     extern char **environ;
  235.     static int done;
  236.     int nenv;
  237.     
  238.     if (end == NULL) return 0;
  239.  
  240.     /* Find a match or count the number of variables in the environment...   */
  241.     for (nenv = 0, tmp = environ; *tmp; tmp++, nenv++) {
  242.    if (strncmp(name, *tmp, end-name)) continue;
  243.    if ((*tmp)[end - name] != '=') continue;
  244.    *tmp = name;
  245.    return 1;
  246.     }
  247.  
  248.     if (!done) {
  249.    if ((tmp = (char **)malloc((nenv + 2) * sizeof(char *))) == NULL) {
  250.        return 0;
  251.    }
  252.  
  253.    memcpy(environ, tmp, nenv+1 * sizeof(char *));
  254.    done = 1;
  255.     } else {
  256.    if ((tmp = (char **)realloc(environ, (nenv + 2) * sizeof(char *))) == NULL) {
  257.        return 0;
  258.    }
  259.     }
  260.  
  261.     tmp[nenv+1] = name;
  262.     tmp[nenv+2] = NULL;
  263.     environ = tmp;
  264.  
  265.     return 1;
  266. #endif
  267. }
  268. #endif
  269.  
  270. /* A function that clears up a given EntryList, for reading or rereading     */
  271. /* the configuration file.   It deallocates any memory used in allocating    */
  272. /* the list to begin with, and memset's the array of entries to be 0...      */
  273. /*                                                                           */
  274. /* Arguments: index -- which index in the confids array to clear up...       */
  275. static void ClearEntryList(confid *confids, int nconfids) {
  276.     int i;
  277.  
  278. #define CLEANUPIND(ind) do { if(*confids[(ind)].array) free(*confids[(ind)].array); *confids[(ind)].array = NULL, *confids[(ind)].number = 0; *confids[(ind)].cnum = 0; } while (0);
  279.  
  280.     for (i = 0; i < *confids[AUTH_IND].number; i++) {
  281.    lsDeleteLinkedList(&((AuthTuple *)*confids[AUTH_IND].array)[i].authlist);
  282.     }
  283.  
  284.     for (i = 0; i < *confids[ROUTE_IND].number; i++) {
  285.         if (((RouteTuple *)*confids[ROUTE_IND].array)[i].nexthop.calloced)
  286.       free(((RouteTuple *)*confids[ROUTE_IND].array)[i].nexthop.ifp);
  287.     }
  288.  
  289.     for (i = 0; i < *confids[PERMIT_IND].number; i++) {
  290.    lsDeleteLinkedList(&((ConfTuple *)*confids[PERMIT_IND].array)[i].command);
  291.    lsDeleteLinkedList(&((ConfTuple *)*confids[PERMIT_IND].array)[i].userlist);
  292.    lsDeleteLinkedList(&((ConfTuple *)*confids[PERMIT_IND].array)[i].authlist);
  293.     }
  294.  
  295.     for (i = 0; i < *confids[SET_IND].number; i++) {
  296.    if (((char **)*confids[SET_IND].array)[i]) {
  297.        MUTEX_LOCK(env_mutex);
  298.        myunsetenv(((char **)*confids[SET_IND].array)[i]);
  299.        MUTEX_UNLOCK(env_mutex);
  300.    }
  301.     }
  302.  
  303.     CLEANUPIND(AUTH_IND);
  304.     CLEANUPIND(PERMIT_IND);
  305.     CLEANUPIND(SOCKS5_IND);
  306.     CLEANUPIND(ROUTE_IND);
  307.     CLEANUPIND(SET_IND);
  308. }
  309.  
  310. static void badline(int ln, char *msg) {
  311.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_WARNING, MSGID_SERVER_CONF_BADLINE, "Conf: Bad line (line number %d) in configuration file: %s", ln, msg);
  312. }
  313.        
  314. /* Examine the current line for an entry setting an environment variable...  */
  315. /*                                                                           */
  316. /* Arguments: indx -- index into the array we are dealing with...(in)        */
  317. /*            i    -- index of the array we came from...(in)                 */
  318. /*            tmp  -- postion in the buffer...(in)                           */
  319. void EvarsHandler(void **array, int indx, int i, char *ptr) {
  320.     /* set up the "environment variables", only from file... */  
  321.     char *tmp, *end1, *new, **vlist = (*(char ***)array), buf[1024];
  322.     int len;
  323.  
  324.     if (indx >= nvlines) {
  325.    S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(1), 0, "Config: Not enough environment variable lines allocated");
  326.    return;
  327.     }
  328.  
  329.     SKIPNONSPACE(ptr);
  330.     SKIPSPACE(ptr);
  331.  
  332.     if ((end1 = strstr(ptr, "\n"))) len = MIN(sizeof(buf)-1, end1-ptr);
  333.     else len = MIN(sizeof(buf)-1, strlen(ptr));
  334.  
  335.     memset(buf, 0, sizeof(buf));
  336.     strncpy(buf, ptr, len);
  337.     buf[len] = '\0';
  338.  
  339.     for (tmp = buf ; !isspace((unsigned char)*tmp) && *tmp != '\0'; tmp++)
  340.    if (islower((unsigned char)*tmp)) *tmp = toupper(*tmp); 
  341.  
  342.     end1 = tmp;
  343.     SKIPSPACE(tmp);
  344.        
  345. #ifndef HAVE_SETENV
  346.     /* mush "variable    value" into "variable=value", and find the end     */
  347.     if (end1 != tmp) for (*end1++ = '='; !isspace((unsigned char)*tmp) && *tmp != '\0'; tmp++, end1++) *end1 = *tmp;
  348.     else *end1++ = '=';
  349.     *end1 = '\0';
  350. #endif
  351.  
  352.     new = strdup(buf);
  353.     MUTEX_LOCK(env_mutex);
  354.  
  355. #ifdef HAVE_SETENV
  356.     new[end1 - buf] = '\0';
  357.     setenv(new, new + (tmp-buf), 1);
  358. #else
  359.     myputenv(new);        /* replace it in actual environ                    */
  360. #endif
  361.  
  362.     MUTEX_UNLOCK(env_mutex);
  363.     vlist[indx] = new;    /* put it in varList for future frees...           */
  364. }
  365.  
  366. /* Examine the current line for an entry setting a filter to use...          */
  367. /*                                                                           */
  368. /* Arguments: indx -- index into the array we are dealing with...(in)        */
  369. /*            i    -- index of the array we came from...(in)                 */
  370. /*            tmp  -- postion in the buffer...(in)                           */
  371. void FilterHandler(void **array, int indx, int i, char *tmp) {
  372.     FilterTuple *entry = &(*(FilterTuple **)array)[indx];
  373.     char *start;
  374.     
  375.     if (indx >= nflines) {
  376.    S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(1), 0, "Config: Not enough filter entries allocated");
  377.    return;
  378.     }
  379.  
  380.     SKIPNONSPACE(tmp);
  381.     entry->realline = lsLineNo;
  382.  
  383.     SKIPSPACE(tmp);
  384.     start = tmp;
  385.     SKIPNONSPACE(tmp);
  386.  
  387.     strncpy(entry->name, start, MIN(tmp-start, S5_NAME_SIZE-1));
  388.     entry->name[MIN(tmp-start, S5_NAME_SIZE-1)] = '\0';
  389.  
  390.     if (lsGetAuthMethods   (&tmp, &entry->authlist) < 0) badline(entry->realline, "auth methods");
  391.     if (lsGetPermCommand   (&tmp, &entry->command)  < 0) badline(entry->realline, "command");
  392.     if (lsGetHostAndMask   (&tmp, &entry->source)   < 0) badline(entry->realline, "source host");
  393.     if (lsGetHostAndMask   (&tmp, &entry->dest)     < 0) badline(entry->realline, "destination host");
  394.     if (lsGetPortOrService (&tmp, &entry->sport)    < 0) badline(entry->realline, "source port");
  395.     if (lsGetPortOrService (&tmp, &entry->dport)    < 0) badline(entry->realline, "destination port");
  396.     if (lsGetPermUsers     (&tmp, &entry->userlist) < 0) badline(entry->realline, "userlist");
  397. }
  398. /* Examine the current line for an entry setting a route to use...           */
  399. /*                                                                           */
  400. /* Arguments: indx -- index into the array we are dealing with...(in)        */
  401. /*            i    -- index of the array we came from...(in)                 */
  402. /*            tmp  -- postion in the buffer...(in)                           */
  403. void RouteHandler(void **array, int indx, int i, char *tmp) {
  404.     RouteTuple *entry = &(*(RouteTuple **)array)[indx];
  405.     
  406.     if (indx >= nrlines) {
  407.    S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(1), 0, "Config: Not enough route entries allocated");
  408.    return;
  409.     }
  410.  
  411.     SKIPNONSPACE(tmp);
  412.     entry->realline = lsLineNo;
  413.     if (lsGetHostAndMask   (&tmp, &entry->source)  < 0) badline(entry->realline, "source host");
  414.     if (lsGetPortOrService (&tmp, &entry->sport)   < 0) badline(entry->realline, "source port");
  415.     if (lsGetHostOrIntfc   (&tmp, &entry->nexthop) < 0) badline(entry->realline, "interface");
  416. }
  417.  
  418. /* Examine the current line for an entry telling us how to get someplace...  */
  419. /*                                                                           */
  420. /* Arguments: indx -- index into the array we are dealing with...(in)        */
  421. /*            i    -- index of the array we came from...(in)                 */
  422. /*            tmp  -- postion in the buffer...(in)                           */
  423. void HowtoHandler(void **array, int indx, int i, char *tmp) {
  424.     static u_short socksport;
  425.     u_short port;
  426.     
  427.     ProxyTuple *entry = &(*(ProxyTuple **)array)[indx];
  428.     SKIPNONSPACE(tmp);
  429.     
  430.     if (indx >= nslines) {
  431.    S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(1), 0, "Config: Not enough proxy entries allocated");
  432.    return;
  433.     }
  434.  
  435.     entry->realline = lsLineNo;
  436.     if (lsGetHostAndMask   (&tmp, &entry->source) < 0) badline(entry->realline, "source host");
  437.     if (lsGetPortOrService (&tmp, &entry->sport)  < 0) badline(entry->realline, "source port");
  438.  
  439.     if (i == DIRECT_IND) {
  440.    entry->nextver   = 0;
  441.    entry->nnextaddr = 0;
  442.    memset((char *)entry->nextaddr, 0, sizeof(S5NetAddr));
  443.    return;
  444.     } 
  445.  
  446.     entry->nextver = (i == SOCKS5_IND)?SOCKS5_VERSION:SOCKS4_VERSION;
  447.  
  448.     for (i = 0; i < S5_SERVER_NUM && *tmp && *tmp != '\n'; i++, tmp++) {
  449.    if (lsGetHostAddressAndPort(&tmp, &entry->nextaddr[i]) < 0) badline(entry->realline, "server address");
  450.  
  451.    if ((port = lsAddr2Port(&entry->nextaddr[i])) == INVALIDPORT || port == (u_short)0) {
  452.        if (!socksport && lsName2Port("socks", "tcp", &socksport) < 0) socksport = htons(SOCKS_DEFAULT_PORT);
  453.        lsAddrSetPort(&entry->nextaddr[i], socksport);
  454.    }
  455.  
  456.    SKIPSPACE(tmp);
  457.  
  458.    if (*tmp != ',') {
  459.        i++;
  460.        break;
  461.    }
  462.     }
  463.  
  464.     entry->nnextaddr = i;
  465. }
  466.  
  467. /* Examine the current line for an entry telling us what is allowed...       */
  468. /*                                                                           */
  469. /* Arguments: indx -- index into the array we are dealing with...(in)        */
  470. /*            i    -- index of the array we came from...(in)                 */
  471. /*            tmp  -- postion in the buffer...(in)                           */
  472. void PermsHandler(void **array, int indx, int i, char *tmp) {
  473.     ConfTuple *entry = &(*(ConfTuple **)array)[indx];
  474.  
  475.     if (indx >= nplines) {
  476.    S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(1), 0, "Config: Not enough permission entries allocated");
  477.    return;
  478.     }
  479.  
  480.     SKIPNONSPACE(tmp);
  481.     entry->realline = lsLineNo;
  482.     entry->permit = (i == PERMIT_IND)?AUTH_OK:AUTH_FAIL;
  483.  
  484.     if (lsGetAuthMethods   (&tmp, &entry->authlist) < 0) badline(entry->realline, "auth methods");
  485.     if (lsGetPermCommand   (&tmp, &entry->command)  < 0) badline(entry->realline, "command");
  486.     if (lsGetHostAndMask   (&tmp, &entry->source)   < 0) badline(entry->realline, "source host");
  487.     if (lsGetHostAndMask   (&tmp, &entry->dest)     < 0) badline(entry->realline, "destination host");
  488.     if (lsGetPortOrService (&tmp, &entry->sport)    < 0) badline(entry->realline, "source port");
  489.     if (lsGetPortOrService (&tmp, &entry->dport)    < 0) badline(entry->realline, "destination port");
  490.     if (lsGetPermUsers     (&tmp, &entry->userlist) < 0) badline(entry->realline, "userlist");
  491. }
  492.  
  493. void AuthsHandler(void **array, int indx, int i, char *tmp) {
  494.     AuthTuple *entry = &(*(AuthTuple **)array)[indx];
  495.  
  496.     if (indx >= nalines) {
  497.    S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(1), 0, "Config: Not enough authentication entries allocated");
  498.    return;
  499.     }
  500.  
  501.     SKIPNONSPACE(tmp);
  502.     entry->realline = lsLineNo;
  503.  
  504.     if (lsGetHostAndMask   (&tmp, &entry->source)   < 0) badline(entry->realline, "source host");
  505.     if (lsGetPortOrService (&tmp, &entry->sport)    < 0) badline(entry->realline, "source port");
  506.  
  507.     if (i != BAN_IND) {
  508.    if (lsGetAuthMethods   (&tmp, &entry->authlist) < 0) badline(entry->realline, "auth methods");
  509.    entry->banned = 0;
  510.     } else {
  511.    entry->banned = 1;
  512.     }
  513.  
  514. }
  515.  
  516. void ReadConfig(void) {
  517.     char *file;
  518.     static int mi = 0;
  519.  
  520.     if (mi == 0) {
  521.         mi++;
  522.         IFTHREADED(MUTEX_SETUP(confid_mutex);)
  523.     }
  524.     MUTEX_LOCK(env_mutex);
  525.     file = getenv("SOCKS5_CONFFILE");
  526.     if (file) file = strdup(file);
  527.     MUTEX_UNLOCK(env_mutex);
  528.  
  529.     if (!file) file = strdup(SRVCONF_FILE);
  530.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Config: Reading config file: %s", file);
  531.  
  532. /*    lsSetupIntfcs(&intfcs, &ifcnt); */
  533.  
  534.     MUTEX_LOCK(confid_mutex);
  535.     ClearEntryList(confids, NCONFIDS);
  536.     lsReadConfig(file, confids, NCONFIDS);
  537.     MUTEX_UNLOCK(confid_mutex);
  538.  
  539.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Config: Config file read");
  540.     if (file) free(file);
  541. /*
  542.     S5LogStart(&S5LogDefaultHandle, -1, -1,"Socks5");
  543. */
  544. }
  545.  
  546. /* See what kind of auths we will have to use...If the client can't do one   */
  547. /* of them, then we'll probably quit.  Otherwise, we'll use this list to     */
  548. /* decide which one we do do...                                              */
  549. int GetAuths(S5LinkInfo *pri, list **authlist) {
  550.     int i;
  551.     
  552.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Checking Authentication");
  553.     *authlist = NULL;
  554.  
  555.     if (nalines == 0) {
  556.    S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Auth: No auth line specified");
  557.    return 0;
  558.     }
  559.  
  560.     MUTEX_LOCK(confid_mutex);
  561.     for (i = 0; i < nalines; i++) {
  562.    if (!lsCheckHost(&authList[i].source, &pri->srcAddr, pri->srcName)) {
  563.        S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Auth: Line %d: Source host didn't match", authList[i].realline);
  564.        continue;
  565.    }
  566.  
  567.    if (pri->peerCommand != SOCKS_PING && pri->peerCommand != SOCKS_TRACER
  568.       && !lsCheckPort(&authList[i].sport, &pri->srcAddr, NULL, (pri->peerCommand == SOCKS_UDP)?"udp":"tcp")) {
  569.        S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Auth: Line %d: Source port didn't match", authList[i].realline);
  570.        continue;
  571.    }
  572.  
  573.    S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Auth: Line %d: Matched", authList[i].realline);
  574.  
  575.    if (authList[i].banned) {
  576.        MUTEX_UNLOCK(confid_mutex);
  577.        return -1;
  578.    } else {
  579.        *authlist = authList[i].authlist;
  580.        MUTEX_UNLOCK(confid_mutex);
  581.        return 0;
  582.    }
  583.     }
  584.  
  585.     MUTEX_UNLOCK(confid_mutex);
  586.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Auth: No line matched");
  587.     return -1;
  588. }
  589.  
  590. /* Check to see if the current set of global variables is allowed to proceed */
  591. /* by the current state of the configuration file.  If we are accepting, we  */
  592. /* don't need to necessariy match the destinaion host and port since they    */
  593. /* are not specified yet...                                                  */
  594. int Authorize(S5LinkInfo *pri, int accepting) {
  595.     int rval, i;
  596.     
  597.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Checking Authorization");
  598.  
  599.     /* Before check with ACL, following address checking is performed:       */
  600.     /*                                                                       */
  601.     /* if src == dst => AUTH_FAIL...                                         */ 
  602.     /* if dst == LOOPBACK => AUTH_FAIL...                                    */ 
  603.     /* if src is one of the next proxy => AUTH_FAIL (avoid looping)...       */ 
  604.     if (pri->peerCommand != SOCKS_UDP && !lsAddrComp(&pri->srcAddr, &pri->dstAddr)) return AUTH_FAIL;
  605.     if (pri->dstAddr.sin.sin_addr.s_addr == htonl(INADDR_LOOPBACK)) return AUTH_FAIL;
  606.  
  607.     for (i = 0; i < pri->nAltSckAddrs; i++) {
  608.       if (!lsAddrComp(&pri->srcAddr, &pri->altSckAddrs[i])) return AUTH_FAIL;
  609.     }
  610.  
  611.     MUTEX_LOCK(confid_mutex);
  612.     for (i = 0; i < nplines; i++) {
  613.    if (!lsCheckByte(accessList[i].command, pri->peerCommand, "commands")) {
  614.        S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Perm: Line %d: Command didn't match", accessList[i].realline);
  615.        continue;
  616.    }
  617.  
  618.    if (!lsCheckByte(accessList[i].authlist, pri->peerAuth, "auths")) {
  619.        S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Perm: Line %d: Authentication didn't match", accessList[i].realline);
  620.        continue;
  621.    }
  622.  
  623.    if (!lsCheckHost(&accessList[i].source, &pri->srcAddr, pri->srcName)) {
  624.        S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Perm: Line %d: Source host didn't match", accessList[i].realline);
  625.        continue;
  626.    }
  627.    
  628.    if (pri->peerCommand != SOCKS_PING && pri->peerCommand != SOCKS_TRACER &&
  629.       !lsCheckPort(&accessList[i].sport, &pri->srcAddr, NULL, (pri->peerCommand == SOCKS_UDP)?"udp":"tcp")) {
  630.        S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Perm: Line %d: Source port didn't match", accessList[i].realline);
  631.        continue;
  632.    }
  633.  
  634.    /* if it is a UDP request, source address matches destination        */
  635.         /* address, and permission is OK, we are done...                     */
  636.    if (pri->peerCommand == SOCKS_UDP && !lsAddrComp(&pri->srcAddr, &pri->dstAddr)) {
  637.        if (accessList[i].permit != AUTH_OK) continue;
  638.  
  639.        S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Perm: Line %d:matched", accessList[i].realline);
  640.        MUTEX_UNLOCK(confid_mutex);
  641.        return AUTH_OK;
  642.    }
  643.  
  644.         /* If we are accepting, we don't know the port. Therefore we should  */
  645.    /* only care about permit lines. If we know the destination address  */
  646.    /* we will check the address.                                        */
  647.         if (accepting) {
  648.        if (accessList[i].permit != AUTH_OK) continue;
  649.        if (lsAddrIsNull(&pri->dstAddr) != 0) {
  650.                if (!lsCheckHost(&accessList[i].dest, &pri->dstAddr, pri->dstName)) {
  651.                     S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Perm: Line %d: Destination host didn't match", accessList[i].realline);
  652.                     continue;
  653.                 }
  654.        }
  655.    } else {
  656.        if (!lsCheckHost(&accessList[i].dest, &pri->dstAddr, pri->dstName)) {
  657.            S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Perm: Line %d: Destination host didn't match", accessList[i].realline);
  658.            continue;
  659.        }
  660.  
  661.        if (!lsCheckPort(&accessList[i].dport, &pri->dstAddr, pri->dstServ, (pri->peerCommand == SOCKS_UDP)?"udp":"tcp")) {
  662.            S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Perm: Line %d: Destination port didn't match", accessList[i].realline);
  663.            continue;
  664.        }
  665.    }
  666.  
  667.    if (!lsCheckUser(accessList[i].userlist, pri->srcUser)) {
  668.        S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Perm: Line %d: Username didn't match", accessList[i].realline);
  669.        continue;
  670.    }
  671.    
  672.    S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Perm: Line %d:matched", accessList[i].realline);
  673.    rval = accessList[i].permit;
  674.    MUTEX_UNLOCK(confid_mutex);
  675.    return rval;
  676.     }
  677.     
  678.     MUTEX_UNLOCK(confid_mutex);
  679.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Perm: No line matched");
  680.     return AUTH_FAIL;
  681. }
  682.  
  683. /* Check the destination is on the same subnet. returns cwnumber of matching */
  684. /* interfaces...                                                             */
  685. static int lsCheckIntfc(const S5NetAddr *dst, S5NetAddr *addr) {
  686.     struct intaddr tmpaddr;
  687.     struct ifreq ifr;
  688.     int i, j, k = 0;
  689.  
  690.     memset((char *)&ifr, 0, sizeof(struct ifreq));
  691.  
  692.     for (i = 0; i < ifcnt; i++) {
  693.    if (intfcs[i].addrcnt == 0 || intfcs[i].up != 1 || intfcs[i].type == 1) {
  694.        /* not an IP interface...                                    */
  695.             if (intfcs[i].up == 1 && intfcs[i].type != 1) continue;
  696.  
  697.        /* the interface is still down...                            */
  698.        strcpy(ifr.ifr_name, intfcs[i].name);
  699.        if (lsLookupIntfc(S5InvalidIOHandle, NET_STAT, &ifr) <= 0) continue;
  700.  
  701.        /* the interface is up now. Find the address and mask, and   */
  702.        /* check if the dst is on the same subnet ...                */
  703.        if (lsLookupIntfc(S5InvalidIOHandle, NET_ADDR, &ifr) < 0) continue;
  704.        if (ifssi(ifr)->sin_family != AF_INET) continue;
  705.        tmpaddr.ip = ifssi(ifr)->sin_addr;
  706.  
  707.        if (lsLookupIntfc(S5InvalidIOHandle, NET_MASK, &ifr) < 0) continue;
  708.             tmpaddr.net = ifssi(ifr)->sin_addr;
  709.  
  710.             if (checkifc(tmpaddr, dst->sin.sin_addr)) {
  711.            addr->sin.sin_addr = tmpaddr.ip;
  712.            k++;
  713.             }
  714.  
  715.        continue; 
  716.    }
  717.  
  718.    /* loopback interface ...                                        */
  719.    if (intfcs[i].addrlist[0].ip.s_addr == htonl(INADDR_LOOPBACK)) continue;
  720.     
  721.    for (j = 0; j < intfcs[i].addrcnt; j++) {
  722.        /* null address and null mask doesn't count ...              */
  723.        if (!(intfcs[i].addrlist[j].ip.s_addr & intfcs[i].addrlist[j].net.s_addr)) continue;
  724.  
  725.        /* on the same subnet...                                     */
  726.             if (checkifc(intfcs[i].addrlist[j], dst->sin.sin_addr)) {
  727.       addr->sin.sin_addr = intfcs[i].addrlist[j].ip;
  728.       k++;
  729.        }
  730.    }
  731.     }
  732.  
  733.     return k;
  734. }
  735.  
  736. /* GetProxy takes the destination and the type of the destination and picks  */
  737. /* how it should and a demand for what kind of server is needed, and finds a */
  738. /* server of that type, or returns -1 if there is no such server.            */
  739. /*                                                                           */
  740. /* Globals used: proxyList, the array of proxy entries....                   */
  741. int GetProxy(const S5NetAddr *dst, const char *name, char *proto, S5NetAddr *sckAddrs, int *nsckAddrs, u_char *verp) {
  742.     int i;
  743.     S5NetAddr tmpaddr;
  744.  
  745.     *verp = 0;
  746.     *nsckAddrs = 0;
  747.  
  748.     if (!lsAddrIsNull(dst)) return 0;
  749.  
  750.     /* Before check the proxy lines, check if the dst is on the same subnet  */
  751.     /* as the server is on.                                                  */
  752.     if (getenv("SOCKS5_NONETMASKCHECK") == NULL) {
  753.    if (lsCheckIntfc(dst, &tmpaddr) > 0) {
  754.             S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Proxy: dst on the same subnet");
  755.             return 0;
  756.         }
  757.     }
  758.  
  759.     MUTEX_LOCK(confid_mutex);
  760.     for (i = 0; i < nslines; i++) {
  761.    if (!lsCheckHost(&proxyList[i].source, dst, name)) {
  762.        S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Proxy: Line %d: Destination host didn't match", proxyList[i].realline);
  763.        continue;
  764.    }
  765.  
  766.    if (!lsCheckPort(&proxyList[i].sport, dst, NULL, proto)) {
  767.        S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Proxy: Line %d: Destination port didn't match", proxyList[i].realline);
  768.        continue;
  769.    }
  770.  
  771. #define REALDEST(x) ((x)->sa.sa_family == AF_INET && (x)->sin.sin_addr.s_addr != INVALIDADDR && (x)->sin.sin_addr.s_addr != INADDR_ANY)
  772.  
  773.    if (proxyList[i].nextver && !REALDEST(&proxyList[i].nextaddr[0])) {
  774.        S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Proxy: Line %d: Invalid server address", proxyList[i].realline);
  775.        continue;
  776.    }
  777.  
  778.    S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Proxy: Line %d: Matched", proxyList[i].realline);
  779.    if (!proxyList[i].nextver) break;
  780.  
  781.    *verp      = proxyList[i].nextver;
  782.    memcpy((char *)sckAddrs, (char *)proxyList[i].nextaddr, sizeof(proxyList[i].nextaddr));
  783.    *nsckAddrs = proxyList[i].nnextaddr;
  784.  
  785.    MUTEX_UNLOCK(confid_mutex);
  786.    return 0;
  787.     }
  788.  
  789.     MUTEX_UNLOCK(confid_mutex);
  790.     return -1;
  791. }
  792.  
  793. /* Determine the outbound address for a given destination           */
  794. /* If not route does match, default will by any interface           */
  795. int GetRoute(const S5NetAddr *dst, const char *name, char *proto, S5NetAddr *addr) {
  796.     struct ifreq ifr;
  797.     int i;
  798.  
  799.     memset((char *)&ifr, 0, sizeof(struct ifreq));
  800.  
  801.     /* If we return before we change this, there was an error...             */
  802.     memset((char *)addr, 0, sizeof(S5NetAddr));
  803.     addr->sin.sin_family = AF_INET;
  804.  
  805.     /* If dst is loopback, the route will be loopback....                    */
  806.     if (dst->sa.sa_family != AF_S5NAME && !lsAddrIsNull(dst)) {
  807.         lsAddrCopy(addr, dst, lsAddrSize(dst));
  808.         lsAddrSetPort(addr, 0);
  809.         return 0;
  810.     }
  811.  
  812.     MUTEX_LOCK(confid_mutex);
  813.  
  814.     for (i = 0; i < nrlines; i++) {
  815.    if (!lsCheckHost(&routeList[i].source, dst, name)) {
  816.        S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Route: Line %d: Destination host didn't match", routeList[i].realline);       
  817.        continue;
  818.    }
  819.  
  820.    if (!lsCheckPort(&routeList[i].sport, dst, NULL, proto)) {
  821.        S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Route: Line %d: Destination port didn't match", routeList[i].realline);       
  822.        continue;
  823.    }
  824.  
  825.    if (routeList[i].nexthop.type == INVALID_TYPE) {
  826.        S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Route: Line %d: Invalid interface type", routeList[i].realline);     
  827.        continue;
  828.    }
  829.  
  830.    if (routeList[i].nexthop.type == NAME) {
  831.        /* If the interface is not up when the daemon started or the interface */
  832.        /* has multiple addresses, get the current active address... otherwise */
  833.        /* we are done...                                                      */
  834.             if (routeList[i].nexthop.ifp->type == 1 || routeList[i].nexthop.ifp->up <= 0 || routeList[i].nexthop.ifp->addrcnt != 1) {
  835.       strcpy(ifr.ifr_name, routeList[i].nexthop.ifp->name);
  836.  
  837.          if (lsLookupIntfc(S5InvalidIOHandle, NET_STAT, &ifr) <= 0) {
  838.                    S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Route: Line %d: Interface is down", routeList[i].realline);
  839.              continue;
  840.       }
  841.  
  842.          if (lsLookupIntfc(S5InvalidIOHandle, NET_ADDR, &ifr) < 0 || ifssi(ifr)->sin_family != AF_INET) {
  843.                    S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Route: Line %d: Invalid interface address", routeList[i].realline);
  844.              continue;
  845.       }
  846.  
  847.       addr->sin.sin_addr = ifssi(ifr)->sin_addr;
  848.       break;
  849.        } else if (routeList[i].nexthop.ifp->addrcnt == 0) continue;
  850.        else {
  851.       addr->sin.sin_addr = routeList[i].nexthop.ifp->addrlist[0].ip;
  852.       break;
  853.        }
  854.    } else {
  855.        addr->sin.sin_addr = routeList[i].nexthop.ifaddr;
  856.        break;
  857.    }
  858.     }
  859.  
  860.     if (i < nrlines) {
  861.    S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Route: Line %d: Matched", routeList[i].realline);      
  862.    MUTEX_UNLOCK(confid_mutex);
  863.    return 0;
  864.     }
  865.  
  866.     /* No match...                                                           */
  867.     MUTEX_UNLOCK(confid_mutex);
  868.  
  869.     /* Before check the route lines, check if the server is single-homed or  */
  870.     /* if the dst is on the same subnet as the server is on. If the server   */
  871.     /* is single-homed, route line is useless. If the dst is on the same     */
  872.     /* subnet, use that interface IP...                                      */
  873.     if (getenv("SOCKS5_NONETMASKCHECK") == NULL) {
  874.    if (lsCheckIntfc(dst, addr) == 1) {
  875.             S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Route: dst on the same subnet");
  876.             return 0;
  877.    }
  878.     }
  879.  
  880.     return -1;
  881. }
  882.  
  883. int GetFilter(S5LinkInfo *pri, char *name) {
  884.     int i;
  885.     
  886.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Checking Filter");
  887.  
  888.     MUTEX_LOCK(confid_mutex);
  889.     for (i = 0; i < nflines; i++) {
  890.    if (!lsCheckByte(filterList[i].command,  pri->peerCommand, "commands")) {
  891.        S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Filter: Line %d: Command didn't match", filterList[i].realline);
  892.        continue;
  893.    }
  894.  
  895.    if (!lsCheckByte(filterList[i].authlist, pri->peerAuth, "auths")) {
  896.        S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Filter: Line %d: Authentication didn't match", filterList[i].realline);
  897.        continue;
  898.    }
  899.  
  900.    if (!lsCheckHost(&filterList[i].source,  &pri->srcAddr, pri->srcName)) {
  901.        S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Filter: Line %d: Source host didn't match", filterList[i].realline);
  902.        continue;
  903.    }
  904.    
  905.    if (!lsCheckPort(&filterList[i].sport,   &pri->srcAddr, NULL, (pri->peerCommand == SOCKS_UDP)?"udp":"tcp")) {
  906.        S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Filter: Line %d: Source port didn't match", filterList[i].realline);
  907.        continue;
  908.    }
  909.  
  910.    if (!lsCheckHost(&filterList[i].dest,    &pri->dstAddr, pri->dstName)) {
  911.        S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Filter: Line %d: Destination host didn't match", filterList[i].realline);
  912.        continue;
  913.    }
  914.  
  915.    if (!lsCheckPort(&filterList[i].dport, &pri->dstAddr, pri->dstServ, (pri->peerCommand == SOCKS_UDP)?"udp":"tcp")) {
  916.        S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Filter: Line %d: Destination port didn't match", filterList[i].realline);
  917.        continue;
  918.    }
  919.  
  920.    if (!lsCheckUser(filterList[i].userlist, pri->srcUser)) {
  921.        S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Filter: Line %d: Username didn't match", filterList[i].realline);
  922.        continue;
  923.    }
  924.    
  925.    S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Filter: Line %d:matched", filterList[i].realline);
  926.    strcpy(name, filterList[i].name);
  927.    MUTEX_UNLOCK(confid_mutex);
  928.    return 0;
  929.     }
  930.     
  931.     MUTEX_UNLOCK(confid_mutex);
  932.     memset(name, 0, S5_NAME_SIZE);
  933.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Filter: No line matched");
  934.     return -1;
  935. }
  936.